﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace LxCFD
{
    public partial class AMGInZone : AMGBase
    {
        public List<MGZone> MgZones { get; set; } = new List<MGZone>();
        public int MaxCoarseLevel { get; set; } = -1;

        public List<int> e_FixValue;
        public List<int> e_ALUO0;
        public List<int> e_Couple;
        public void checkTopology()
        {
            Console.WriteLine("粗网格层数：{0} maxCoarse:{1}", MgZones.Count, MaxCoarseLevel);
            for (int i1 = 0; i1 < MgZones.Count; i1++)
            {
                Console.WriteLine("第 {0} 层粗网格：Cell数量{1}，Face数量{2}。", i1, MgZones[i1].Cells.Length, MgZones[i1].Faces.Length);
            }
        }
        public void Create(MGMeshCreator commonData, IProvideZoneTopology startZone, int startZoneCellLength, double[] zoneCellCommonArray)
        {
            //创建多重网格
            MGZoneCreator zoneCreator = commonData.zoneCreator;
            //if (zoneCreator.InCoarseCell == null || zoneCreator.InCoarseCell.Length < startZoneCellLength)
            //{
            //    zoneCreator.InCoarseCell = new int[startZoneCellLength];
            //}
            MgZones.Clear();
            MGZone mgzone = zoneCreator.CreateMGZone(startZone);
            MgZones.Add(mgzone);
            MaxCoarseLevel = 0;
            while (MgZones.Count < commonData.maxCoarseLevelLimit)
            {
                MGZone fineZone = MgZones[MgZones.Count - 1];
                MGZone coarseZone = zoneCreator.CreateMGZone(fineZone);
                if (fineZone.Cells.Length > coarseZone.Cells.Length)
                {
                    MaxCoarseLevel = MgZones.Count;
                }
                MgZones.Add(coarseZone);
            }
            //设置数组
            foreach (var cz in MgZones)
            {
                cz.CreateArray(this, zoneCellCommonArray);
            }
            for (int i1 = 1; i1 < MgZones.Count; i1++)
            {
                MgZones[i1].SetFinerZone(MgZones[i1 - 1]);
            }
        }
        public void LinkToMatrix(IAMGSolvableZone matrix)
        {
            MgZones[0].SetFinerZone(matrix);
            matrix.GetBounds(out e_FixValue, out e_ALUO0, out e_Couple);
            isNeededUpdateA = true;
        }
        public void Restrict(int taskIndex)
        {
            if (isNeededUpdateA)
            {
                MgZones[SolvingLevel].Restrict_ArLUe(taskIndex);
            }
            else
            {
                MgZones[SolvingLevel].Restrict_re(taskIndex);
            }
        }
        public void Prolong(int taskIndex)
        {
            MgZones[SolvingLevel].Prolong(taskIndex);
        }
    }
    public partial class AMGInZone : IProvideVariableCount
    {
        public BiCGStabInZone BiCGSolver { get; set; }
        public int GetVariableCount()
        {
            return MgZones[0].Cells.Length;
        }
    }
    public partial class AMGInZone : ISolvableZone
    {
        public double Max_acPhic = 0;
        public double Max_Rc = 0;
        public void CalResidual(int taskIndex)
        {
            MgZones[SolvingLevel].CalResidual(taskIndex);
        }
        public void GetResidual_Reset(out double MaxRc, out double MaxacPhic)
        {
            MaxRc = Max_Rc;
            MaxacPhic = Max_acPhic;
            Max_Rc = 0;
            Max_acPhic = 0;
        }
    }
    public partial class AMGInZone 
    {
        public void CalByJacobi_Step1(int taskIndex)
        {
            MgZones[SolvingLevel].CalByJacobi_Step1(taskIndex);
        }

        public void CalByJacobi_Step2(int taskIndex)
        {
            MgZones[SolvingLevel].CalByJacobi_Step2(taskIndex);
        }
    }
    public partial class AMGInZone 
    {
        public void Cal_pArray(int taskIndex)
        {
            MgZones[SolvingLevel].Cal_pArray(taskIndex);
        }

        public void Cal_rArray(int taskIndex)
        {
            MgZones[SolvingLevel].Cal_rArray(taskIndex);
        }

        public void Cal_rhoPart1(int taskIndex)
        {
            MgZones[SolvingLevel].Cal_rhoPart1(taskIndex);
        }

        public void Cal_sArray(int taskIndex)
        {
            MgZones[SolvingLevel].Cal_sArray(taskIndex);
        }

        public void Cal_tArray_omega1(int taskIndex)
        {
            MgZones[SolvingLevel].Cal_tArray_omega1(taskIndex);
        }

        public void Cal_vArray_alpha1(int taskIndex)
        {
            MgZones[SolvingLevel].Cal_vArray_alpha1(taskIndex);
        }

        public void Cal_xArray(int taskIndex)
        {
            MgZones[SolvingLevel].Cal_xArray(taskIndex);
        }

        public void Cal_yArray(int taskIndex)
        {
            MgZones[SolvingLevel].Cal_yArray(taskIndex);
        }

        public void Cal_zArray(int taskIndex)
        {
            MgZones[SolvingLevel].Cal_zArray(taskIndex);
        }

        public void Initialize_Step1_r0rp1rho(int taskIndex)
        {
            MgZones[SolvingLevel].Initialize_Step1_r0rp1rho(taskIndex);
        }
    }
}
//public class ADiagLU
//{
//    public ADiagLU(int cellCount, int faceCount)
//    {
//        this.A_Diag = new double[cellCount];
//        this.A_LU_O = new double[faceCount];
//        this.A_LU_N = new double[faceCount];
//    }
//    public ADiagLU(MGZone zone)
//    {
//        this.A_Diag = new double[zone.Cells.Length];
//        this.A_LU_O = new double[zone.Faces.Length];
//        this.A_LU_N = new double[zone.InnerIndex.FaceIDs.End + 1];
//    }
//    public double[] A_Diag { get; set; }
//    public double[] A_LU_O { get; set; }
//    public double[] A_LU_N { get; set; }

//}
//public List<ADiagLU> MGLocal_A { get; set; }
//this.MGLocal_A = CreateA();
//link_A_Diag_LU(MGLocal_A);
//public List<ADiagLU> CreateA()
//{
//    List<ADiagLU> coarseMeshAs = new List<ADiagLU>();
//    foreach (MGZone cz in MgZones)
//    {
//        ADiagLU mga = new ADiagLU(cz);
//        coarseMeshAs.Add(mga);
//    }
//    return coarseMeshAs;
//}
//private void link_A_Diag_LU(List<ADiagLU> A_DiagLUs)
//{
//    if (MgZones.Count != A_DiagLUs.Count) throw new Exception("数据长度不匹配");
//    for (int i1 = 0; i1 < MgZones.Count; i1++)
//    {
//        MgZones[i1].SetADLUArray(A_DiagLUs[i1].A_Diag, A_DiagLUs[i1].A_LU_O, A_DiagLUs[i1].A_LU_N);
//    }
//}